<template>
    <el-space direction="vertical" fill class="menu-check">
      <div class="menu-check__header">
        <el-input v-model="keyword" placeholder="输入关键字进行过滤" />
      </div>
  
      <el-scrollbar class="menu-check__body" height="200">
        <el-tree
          ref="treeRef"
          :data="treeData"
          :props="defaultProps"
          :filter-node-method="filterNode"
          node-key="id"
          show-checkbox
          default-expand-all
          @check="handleChange"
        />
      </el-scrollbar>
  
      <!-- <el-button @click="fn1">获取当前勾选的 菜单Id 集合</el-button> -->
  
      <!-- <el-button @click="fn2">设置当前勾选的 菜单Id 集合</el-button> -->
    </el-space>
  </template>
  
  <script>
  import { getMenuListAll } from "@/api/system";
  import { deepTree } from "@/utils/common";
  
  export default {
    name: "MenuCheck",
  
    props: {
      modelValue: {
        type: Array,
        default: () => [],
      },
    },
  
    emits: ["update:modelValue"],
  
    data() {
      return {
        keyword: "", // 搜索关键字
        list: [],
        defaultProps: {
          label: "name",
          // children: "children",
        },
      };
    },
  
    computed: {
      treeData() {
        return deepTree(this.list);
      },
    },
  
    watch: {
      modelValue: {
        handler() {
          this.set();
        },
        deep: true,
        immediate: true,
      },
  
      list: {
        handler() {
          this.set();
        },
        immediate: true,
      },
  
      keyword(newVal) {
        this.$refs.treeRef.filter(newVal);
      },
    },
  
    methods: {
      /**
       * 过滤节点的函数
       *    触发时机: 当我们执行 Tree 组件实例的 filter() 方法时
       *
       *    参数:
       *        1. value - 调用 Tree实例的 filter() 时传递过来的参数
       *        2. node  - 当前节点数据
       *    返回值:
       *        true     - 当前节点显示
       *        false    - 当前节点隐藏
       */
      filterNode(value, node) {
        // console.log("filterNode value", value);
        // console.log("filterNode node", node);
        return node.name.includes(value);
      },
  
      /**
       * 是否为叶子节点
       * @param {*} id 节点Id
       * @returns {boolean}
       */
      isLeaf(id) {
        const tmp = this.list.find((item) => item.parentId === id);
        return !tmp;
      },
  
      /**
       * 设置勾选
       */
      set() {
        // 1. 过滤出叶子节点
        const keys = this.modelValue.filter((item) => this.isLeaf(item));
        // 2. 设置
        this.$refs.treeRef?.setCheckedKeys(keys);
      },
  
      /**
       * el-tree 勾选时触发
       * @param {*} node 当前节点
       * @param {*} checkedKeys 勾选的节点Id集合
       * @param {*} halfCheckedKeys 半勾选的节点Id集合
       */
      handleChange(node, { checkedKeys, halfCheckedKeys }) {
        // 组装 checkedKeys 与 halfCheckedKeys
        const tmp = [...checkedKeys, ...halfCheckedKeys];
        this.$emit("update:modelValue", tmp);
      },
  
      async refresh() {
        try {
          const result = await getMenuListAll();
          // console.log("result", result);
          this.list = result;
        } finally {
          // ...
        }
      },
  
      // fn1() {
      //   // 获取勾选的
      //   const checkedKeys = this.$refs.treeRef.getCheckedKeys();
      //   // 获取半勾选的
      //   const halfCheckedKeys = this.$refs.treeRef.getHalfCheckedKeys();
      //   console.log("checkedKeys", checkedKeys);
      //   console.log("halfCheckedKeys", halfCheckedKeys);
      // },
  
      // fn2() {
  
      //   /**
      //    * 后端返回数据是 [1, 2, 4] 使用下面方面会把Id为3的也给勾选，这是不对的。如何解决？？？
      //    *
      //    * 思考
      //    *    [1, 2, 4] => [2, 4]
      //    *    [5, 7, 14] => [14]
      //    *
      //    * 叶子节点：没有子级的节点
      //    *
      //    * 过滤出属于叶子节点的Id
      //    */
      //   // const ids = [5, 7, 14].filter((item) => this.isLeaf(item));
      //   // console.log("ids", ids);
  
      //   // this.$refs.treeRef.setCheckedKeys(ids);
      // },
    },
  
    created() {
      this.refresh();
    },
  };
  </script>
  
  <style lang="scss" scoped>
  .menu-check {
    display: flex;
    width: 100%;
  
    &__body {
      padding: 10px;
      box-shadow: 0 0 0 1px #dcdfe6 inset;
      border-radius: 4px;
    }
  }
  </style>
  